#pragma once

#include "ServerChannelCore.h"
#include "SessionWatcher.h"
#include "VcServerUtils.h"

namespace rdc_transport
{
    namespace Server
    {
        template<class WriteStrategy_t, class ReadStrategy_t>
        class ChannelBuilder
        {
        private:
            typedef CVirtualChannel<ServerChannelCore<SessionWatcher>, ReadStrategy_t, WriteStrategy_t> VirtualChannel;
            typedef std::auto_ptr<ServerChannelCore<SessionWatcher>> pChannelCore;

        public:
            pChannelCore CreateChannelCore(const char* channelName, LPTSTR szAddinRGSName)
            {
                std::auto_ptr<SessionWatcher> sw(new SessionWatcher(szAddinRGSName));
                return pChannelCore(new ServerChannelCore<SessionWatcher>(channelName, sw));
            }

            void RegistreConnectionObserver(SessionWatcher* sw, IServerVirtChannelCallback* pCallback)
            {
                sw->AddDisconnectHandler(boost::bind(&IServerVirtChannelCallback::OnDisconnect, pCallback));
                sw->AddReconnectHandler(boost::bind(&IServerVirtChannelCallback::OnReconnect, pCallback));
            }

            std::auto_ptr<IVirtChannel> GetResult(const char* szChannelName, LPTSTR szAddinRGSName, IServerVirtChannelCallback* pCallback, IReadHandler* pReadHandler)
            {
                if(!ChannelDoesExist(szChannelName))
                    throw std::runtime_error(std::string(__FUNCTION__) + " Channel does not exist");

                pChannelCore core = CreateChannelCore(szChannelName, szAddinRGSName);
                RegistreConnectionObserver(core->GetSessionInfo(), pCallback);
                
                std::auto_ptr<ReadStrategy_t> rs(new ReadStrategy_t(core.get()));
                core->GetSessionInfo()->AddReconnectHandler(boost::bind(&ReadStrategy_t::OnReconnect, rs.get()));
                
                std::auto_ptr<WriteStrategy_t> ws(new WriteStrategy_t());

                std::auto_ptr<IVirtChannel> res(new VirtualChannel(pReadHandler, core, rs, ws));
                return res;
            }
        };
    }
}